iT邦幫忙

1

[ JS個人筆記 ] 傳值傳址&深淺層拷貝—DAY5

  • 分享至 

  • xImage
  •  

傳值(call by value)vs傳址(call by reference)

  • 基本型別(Number、String、Boolean、null、undefined)屬於 call by value。
  • 物件型別(Array、Object、function) 為 call by reference。

1. 傳值

當資料為基本型別(如 string、number、boolean、null、undefined),那麼即為賦值。

let a = 10
let b = 10

console.log(a === b) // true

a 更新後不會影響 b

let a = 10
let b = a
a = 20

console.log(a === b) // false

2.傳址

當資料為物件型別(Array、Object、function),那麼即為賦址。

var obj1 = { v1: 1 };
var obj2 = { v1: 1 };

console.log( obj1 === obj2 );  // false

因為兩者的記憶體位置並不相同。在比較物件型別時,比較的是記憶體位置,而非值。

let obj1 = { v1: 1 };
let obj2 = obj1;

obj1.v1 = 0;

console.log( obj2.v1 );  // 0

obj2.v2 = 2;

console.log( obj1.v2 );  // 2
console.log( obj1 === obj2 );  // true

當我們修改任意物件屬性時,另一邊的屬性也會更動,這是因為兩個變數指向相同的記憶體位置,並沒有新的物件被複製出來。

注意例外

  • pass by sharing => 當物件被傳入function當參數且物件被重新賦址時,物件是不會被影響的。
let obj1 = { v1: 1 };

function change(e){
e = {v1:100};
console.log(obj1)   //{ v1: 1 }
}
change(obj1)
console.log(obj1)   //{ v1: 1 }

若改成以下,則可變更資料

let obj1 = { v1: 1 };

function change(e){
console.log(obj1)   // { v1: 1 }
e.v1=100;
}

change(obj1)
console.log(obj1)  //{ v1: 100 }

淺層拷貝vs深層拷貝

  • 淺層拷貝:複製資料只能複製第一層,因為深層的物件或陣列還是傳址,不會完全複製一份
  • 深層拷貝:深拷貝就是完全複製一份,不會有共用記憶體的問題

1.淺層拷貝常見方法

  • 物件的淺拷貝
    • Object.assign()
    • 展開運算子 ...
  • 陣列的淺拷貝
    • slice()
    • concat()
    • forEach + push()
    • map()
    • filter()
    • ... 展開運算子

2.深層拷貝常見方法

  • 利用 JSON 方法:先轉 JSON 格式,再轉回來。
  • 第三方函式庫
    • jQuery 的 $.extend
    • Lodash 的 _.cloneDeep()

更詳細內容請參考 竹白筆記

面試題目

1.b 會呈現什麼答案?

let a = {};
let b = a ;
let c = b = {number:1};
c.name = "tom";
console.log(b)

Ans:{number:1,name:tom}
在第三行,c、b皆指向{number:1}
2.請問 console.log(hello.a)、console.log(a)會出現什麼?

function hello(){
  a = 1;
}
hello.a = "hi";
hello();
console.log(hello.a)
console.log(a)

Ans:hi、1

3.console.log(family[0].members.bro)會是?

let family = [{
  name:"tom",
  members:{
    mon:'媽',
    dad:'爸',
    bro:'哥',
  }
}]

let newArray = [];

family.forEach((item)=>{
  newArray.push(item);
})

newArray[0].members.bro = '弟' ;
console.log(family[0].members.bro)

Ans:弟
因淺層拷貝,故深層指向被複製的物件

4.console.log(family.name)、console.log(family.members.mon)會是?

let family = {
  name:"tom",
  members:{
    mon:'媽',
    dad:'爸',
    bro:'哥',
  }
};

let newfamily = {...family};
newfamily.name = 'ted';
newfamily.members.mon = "momy" ;

console.log(family.name)
console.log(family.members.mon)

Ans:tom、momy


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言